/* 
Scenic Graphics Library
Copyright (C) 2007 Jouni Tulkki

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USApackage scenic;
*/

package scenic;

import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.util.Vector;

import scenic.path.Path;
import scenic.path.PathWalker;

class Tesselator {
	private class Walker implements PathWalker
	{
		public Walker() {
		}
		
		public void beginSubPath(boolean isClosed) {
			beginContour(id);			
		}

		public void endSubPath() {
			endContour(id);			
		}
	
		public void lineTo(double x, double y) {
			vertex(id, x, y);			
		}
	}
	
	private class Triangle
	{
		int vertex1;
		boolean edge1;
		int vertex2;
		boolean edge2;
		int vertex3;
		boolean edge3;
	}
	private int id;
	public Vector<Point2D.Double> vertices = new Vector<Point2D.Double>();
	public Vector<Triangle> triangles = new Vector<Triangle>();
	private boolean cacheTriangles = true;
	private Path path;
	private DrawContext context;
	
	public Tesselator(Path path) {
		this.path = path;
	}
	
	public void setPath(Path path) {
		this.path = path;
		free();
	}
	
	public void free() {
		if(id != 0)
		{
			free(id);
			id = 0;
		}		
	}
	
	protected void finalize() {
		free();
	}
	
	public void draw(DrawContext context, AffineTransform transform) {
		if(id == 0) {
			id = begin(path.isConvex(), context.context);
			path.walk(new Walker(), transform, context.pathError);
			end(id);
		}
		draw(id, context.context);
		if(!cacheTriangles) {
			free(id);
			id = 0;
		}
	}
	
	private native int begin(boolean isConvex, int contextId);
	private native void end(int id);
	private native void free(int id);
	private native void beginContour(int id);
	private native void endContour(int id);
	private native void vertex(int id, double x, double y);
	private native void draw(int id, int contextId);
	
	@SuppressWarnings("unused") // Called from native code
	private void addVertex(double x, double y) {
		if(cacheTriangles)
			vertices.add(new Point2D.Double(x, y));
		else
			context.renderer.tessVertex(context.context, x, y);
	}
	
	@SuppressWarnings("unused") // Called from native code
	private void addTriangle(int vertex1, boolean edge1, int vertex2, boolean edge2, 
			int vertex3, boolean edge3) {
		if(cacheTriangles) {
			Triangle t = new Triangle();
			
			t.vertex1 = vertex1;
			t.edge1 = edge1;
			t.vertex2 = vertex2;
			t.edge2 = edge2;
			t.vertex3 = vertex3;
			t.edge3 = edge3;
			triangles.add(t);			
		} else {
			context.renderer.tessTriangle(context.context, vertex1, edge1, vertex2, edge2,
				vertex3, edge3);
		}
	}
}
